package com.cac.demo.newCode.cemop.utils;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.cac.demo.controller.compressedFiles.CompressedFilesEditor;
import com.cac.demo.newCode.cemop.dto.CemopXmlDTO;
import com.cac.demo.newCode.cemop.enums.CemopXmlEnum;
import com.cac.demo.util.adapter.ComUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import javax.annotation.Resource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
@Slf4j
@Component
public class CemopXmlUtil {
    @Resource
    private Environment environment;
    @Resource
    private CompressedFilesEditor compressedFilesEditor;

    public JSONObject createXml(CemopXmlDTO dto) {
        try {
            // 创建DocumentBuilderFactory对象
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            // 创建DocumentBuilder对象
            DocumentBuilder builder = factory.newDocumentBuilder();
            // 创建Document对象
            Document doc = builder.newDocument();
            // 创建根元素
            Element rootElement = doc.createElement("root");
            doc.appendChild(rootElement);
            //第一层 是表名
            List<CemopXmlDTO> tableDTOs = dto.getCemopXmlDTOList();
            for (CemopXmlDTO tableDTO : tableDTOs) {
                // 创建子元素
                Element childElement = doc.createElement(tableDTO.getXmlName());
                rootElement.appendChild(childElement);
                //第二层 是字段名
                List<CemopXmlDTO> fieldDTOs = tableDTO.getCemopXmlDTOList();
                for (CemopXmlDTO fieldDTO : fieldDTOs) {
                    String fieldName = fieldDTO.getXmlName();
                    String fieldValue = fieldDTO.getXmlValue();
                    childElement.setAttribute(fieldName, fieldValue);
                }
            }
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            DOMSource source = new DOMSource(doc);
            StringWriter writer = new StringWriter();
            StreamResult result = new StreamResult(writer);
            transformer.transform(source, result);
            String xmlString = writer.toString();
            byte[] byteArray = xmlString.getBytes(StandardCharsets.UTF_8);

            String LINUX_FIXED_DIR = environment.getProperty("cemopUrl.linuxFixedDir");
            String format = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);
            File folder = new File(LINUX_FIXED_DIR + format);
            if (!folder.isDirectory()) {
                folder.mkdirs();
            }
            String filename = ComUtil.getId();
            String xmlFileName = filename + ".xml";
            String zipFileName = filename + ".zip";
            // 将JSON数据保存为.xml文件
            Path xmlFilePath = Paths.get(folder.getAbsolutePath(), xmlFileName);
            Files.write(xmlFilePath, byteArray);
            // 压缩.xml文件为.zip文件
            Path zipFilePath = Paths.get(folder.getAbsolutePath(), zipFileName);
            try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFilePath.toFile()))) {
                ZipEntry zipEntry = new ZipEntry(xmlFilePath.getFileName().toString());
                zos.putNextEntry(zipEntry);
                Files.copy(xmlFilePath, zos);
                zos.closeEntry();
            }
            System.out.println("=====================zip文件保存成功========================");
            // 删除.xml文件
            Files.deleteIfExists(xmlFilePath);
            String getfileurl = environment.getProperty("cemopUrl.getfileurl");
            // 返回上传文件的访问路径
            String fileDownloadUri = getfileurl + format + "/" + zipFileName;
            System.out.println("=====================生成下载url========================" + fileDownloadUri);
            String url = environment.getProperty("cemopUrl.proxy");
            System.out.println("=========================fileSend文件发送地址=============================："+url);
            JSONObject sendData = new JSONObject();
            Map<String, Object> BDataMap = new HashMap<>();
            String bKey = IdUtil.simpleUUID();
            sendData.put("bKey",bKey);
            sendData.put("filePath","");//生成的压缩包路径
            sendData.put("fileUrl", fileDownloadUri);
            sendData.put("auditMap", "");
            String cemopUrl="";
            switch (dto.getXmlType()){
                case "4":
                    cemopUrl=environment.getProperty( "cemopUrl."+CemopXmlEnum.SUPPORTING_MATERIALS.getValue());
                    break;
                case "5":
                    cemopUrl=environment.getProperty( "cemopUrl."+CemopXmlEnum.DELIVERY.getValue());
                    break;
                case "6":
                    cemopUrl=environment.getProperty( "cemopUrl."+CemopXmlEnum.SUPPORTING_INFORMATION.getValue());
                    break;
                case "7":
                    cemopUrl=environment.getProperty( "cemopUrl."+CemopXmlEnum.CANCEL_DELIVERY.getValue());
                    break;
                case "14":
                    cemopUrl=environment.getProperty( "cemopUrl."+CemopXmlEnum.AGREE_MATERIAL_RETURN.getValue());
                    break;
                case "15":
                    cemopUrl=environment.getProperty( "cemopUrl."+CemopXmlEnum.REJECT_MATERIAL_RETURN.getValue());
                    break;
                case "16":
                    cemopUrl=environment.getProperty( "cemopUrl."+CemopXmlEnum.AGREE_SECOND_MATCH.getValue());
                    break;
                case "17":
                    cemopUrl=environment.getProperty( "cemopUrl."+CemopXmlEnum.REJECT_SECOND_MATCH.getValue());
                    break;
                case "18":
                    cemopUrl=environment.getProperty( "cemopUrl."+CemopXmlEnum.SHOP_MATERIAL_DELIVERY.getValue());
                    break;
                default:
                    // 处理其他情况
                    cemopUrl="";
                    break;
            }
            BDataMap.put("fileSendUrl",cemopUrl);//Cemop接口路径
            BDataMap.put("fileSendMsgUrl", "");
            sendData.put("BData", BDataMap);
            System.out.println("=====================Cemop两网传输调用代理服务器传递参数========================："+sendData.toString());

            String rs = com.cac.demo.util.HttpUtil.post(url, sendData.toJSONString());
            System.out.println("=====================Cemop两网传输调用代理服务器返回参数========================："+rs);
            return sendData;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public  List<File> downloadAndExtractXMLFiles(String fileUrl) {
        Path tempZipFilePath = null;
        Path tempDirPath = null;
        List<File> xmlFiles = new ArrayList<>();

        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            // 下载压缩文件
            HttpGet request = new HttpGet(fileUrl);
            try (CloseableHttpResponse response = httpClient.execute(request);
                 InputStream zipStream = response.getEntity().getContent()) {

                tempZipFilePath = Files.createTempFile("downloaded", ".zip");
                Files.copy(zipStream, tempZipFilePath, StandardCopyOption.REPLACE_EXISTING);
            }

            // 创建解压文件夹
            tempDirPath = Files.createTempDirectory("unzipped");
            unzip(tempZipFilePath, tempDirPath);

            // 获取解压后的所有XML文件并转为File类型
            try (DirectoryStream<Path> stream = Files.newDirectoryStream(tempDirPath, "*.xml")) {
                for (Path entry : stream) {
                    xmlFiles.add(entry.toFile()); // 将每个XML文件路径转换为File对象
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 删除临时下载文件
            try {
                if (tempZipFilePath != null){
                    Files.deleteIfExists(tempZipFilePath);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return xmlFiles; // 返回所有XML文件的File对象集合
    }


    /**
     * 下载并解压指定URL的ZIP文件，返回解压后的所有XML文件的File对象集合。
     *
     * @param fileUrl ZIP文件的URL
     * @return 解压后的所有XML文件的File对象集合
     */
    public  List<File> downloadAndExtractXMLFile(String fileUrl) {
        Path tempZipFilePath = null;
        Path tempDirPath = null;
        List<File> xmlFiles = new ArrayList<>();
        //是创建HTTP客户端，并设置请求配置，包括连接超时和读取超时时间-暂时为5秒
        try (CloseableHttpClient httpClient = HttpClients.custom()
                .setDefaultRequestConfig(RequestConfig.custom()
                        .setSocketTimeout(5000)
                        .setConnectTimeout(5000)
                        .build())
                .build()) {
            // 下载压缩文件
            HttpGet request = new HttpGet(fileUrl);
            try (CloseableHttpResponse response = httpClient.execute(request);
                 InputStream zipStream = response.getEntity().getContent()) {
                tempZipFilePath = Files.createTempFile("downloaded", ".zip");
                Files.copy(zipStream, tempZipFilePath, StandardCopyOption.REPLACE_EXISTING);
            }
            // 创建解压文件夹
            tempDirPath = Files.createTempDirectory("unzipped");
            unzip(tempZipFilePath, tempDirPath);
            // 获取解压后的所有XML文件并转为File类型
            try (Stream<Path> stream = Files.list(tempDirPath)) {
                stream.filter(path -> path.toString().endsWith(".xml"))
                        .map(Path::toFile)
                        .forEach(xmlFiles::add);
            }
        } catch (IOException e) {
            log.error("Error downloading and extracting XML files: " + e.getMessage(), e);
            return Collections.emptyList(); // 返回空列表
        } finally {
            // 删除临时下载文件
            try {
                if (tempZipFilePath != null) {
                    Files.deleteIfExists(tempZipFilePath);
                }
       /*         if (tempDirPath != null) {
                    deleteDirectory(tempDirPath);
                }*/
            } catch (IOException e) {
                log.error("Error deleting temporary files: " + e.getMessage(), e);
            }
        }
        return xmlFiles; // 返回所有XML文件的File对象集合
    }
    /**
     * 递归删除目录及其子文件。
     *
     * @param dir 要删除的目录
     * @throws IOException 如果删除过程中发生错误
     */
    private static void deleteDirectory(Path dir) throws IOException {
        Files.walk(dir)
                .sorted(Comparator.reverseOrder())
                .map(Path::toFile)
                .forEach(File::delete);
    }

    private static void unzip(Path zipFilePath, Path destDir) throws IOException {
        try (ZipInputStream zis = new ZipInputStream(Files.newInputStream(zipFilePath))) {
            ZipEntry zipEntry = zis.getNextEntry();
            while (zipEntry != null) {
                Path newFile = destDir.resolve(zipEntry.getName());
                if (zipEntry.isDirectory()) {
                    Files.createDirectories(newFile);
                } else {
                    Files.createDirectories(newFile.getParent());
                    try (OutputStream fos = Files.newOutputStream(newFile)) {
                        byte[] buffer = new byte[1024];
                        int len;
                        while ((len = zis.read(buffer)) > 0) {
                            fos.write(buffer, 0, len);
                        }
                    }
                }
                zipEntry = zis.getNextEntry();
            }
        }
    }

    public <T> CemopXmlDTO createTableDTO(String tableName, Map<String, String> fieldMap) {
        CemopXmlDTO tableDTO = new CemopXmlDTO();
        tableDTO.setXmlName(tableName);

        List<CemopXmlDTO> fieldDTOs = new ArrayList<>();
        for (Map.Entry<String, String> entry : fieldMap.entrySet()) {
            String fieldName = entry.getKey();
            String fieldValue = entry.getValue();
            try {
                if (fieldName != null || fieldValue != null) {
                    addFieldDTO(fieldDTOs, fieldName, fieldValue);
                } else {
                    log.warn("字段值不是字符串类型，跳过添加字段: fieldName={}, fieldValue={}", fieldName);
                }
            } catch (Exception e) {
                log.error("获取字段值失败: fieldName={}", fieldName, e);
            }
        }

        tableDTO.setCemopXmlDTOList(fieldDTOs);
        return tableDTO;
    }


    public <T> CemopXmlDTO createTableDTOs(Object tableName, Map<String, Object> fieldMap) {
        CemopXmlDTO tableDTO = new CemopXmlDTO();
        tableDTO.setXmlName(String.valueOf(tableName));

        List<CemopXmlDTO> fieldDTOs = new ArrayList<>();
        for (Map.Entry<String, Object> entry : fieldMap.entrySet()) {
            String fieldName = entry.getKey();
            Object fieldValue = entry.getValue();
            try {
                if (fieldName != null || fieldValue != null) {
                    addFieldDTOs(fieldDTOs, fieldName, fieldValue);
                } else {
                    log.warn("字段值不是字符串类型，跳过添加字段: fieldName={}, fieldValue={}", fieldName);
                }
            } catch (Exception e) {
                log.error("获取字段值失败: fieldName={}", fieldName, e);
            }
        }

        tableDTO.setCemopXmlDTOList(fieldDTOs);
        return tableDTO;
    }

    public void addFieldDTO(List<CemopXmlDTO> fieldDTOs, String fieldName, String fieldValue) {
        if (fieldName != null && fieldValue != null) {
            CemopXmlDTO fieldDTO = new CemopXmlDTO();
            fieldDTO.setXmlName(fieldName);
            fieldDTO.setXmlValue(String.valueOf(fieldValue));
            fieldDTOs.add(fieldDTO);
        } else {
            log.warn("字段名或字段值为空，跳过添加字段: fieldName={}, fieldValue={}", fieldName, fieldValue);
        }
    }

    public void addFieldDTOs(List<CemopXmlDTO> fieldDTOs, String fieldName, Object fieldValue) {
        if (fieldName != null && fieldValue != null) {
            CemopXmlDTO fieldDTO = new CemopXmlDTO();
            fieldDTO.setXmlName(fieldName);
            fieldDTO.setXmlValue(String.valueOf(fieldValue));
            fieldDTOs.add(fieldDTO);
        } else {
            log.warn("字段名或字段值为空，跳过添加字段: fieldName={}, fieldValue={}", fieldName, fieldValue);
        }
    }
}

